using System;
using System.IO;
using System.Collections.Generic;
using MathSharp;
using System.Linq;

namespace MathSharp.Script
{
	public class CommandsBlock: BaseCommand
	{
		List<BaseCommand> commands;
		
		public CommandsBlock (Namespace ns): base(ns)
		{
			commands = new List<BaseCommand>();
		}
		
		public override Value Execute ()
		{
			base.Execute();
			Value result = null;
			foreach (BaseCommand command in commands) {
				Value lastRes = command.Execute();
				if (lastRes != null)
					result = lastRes;
			}
			return result;
		}
		
		List<string> PrepareFragmentForParse(IList<string> fragment) {
			// определяем табулятор
			string firstLine = fragment[0];
			char tabSymbol = firstLine[0];
			int tabSymbosCount = 0;
			while (tabSymbosCount < firstLine.Length && firstLine[tabSymbosCount] == tabSymbol)
				tabSymbosCount++;
			tabSymbosCount--;
			string tabChars = firstLine.Substring(0, tabSymbosCount);
			
			// преверяем что табулятор одинаковый у всего блока
			for (int i = 0; i < fragment.Count; i++)
				if (!fragment[i].StartsWith(tabChars))
					throw new ParseException(script.FileName, fragment.GetOriginalLineSmarts(i), 0, 0x0, "Неверно заданы отступы");
			
			// создаём новый список с убраным табулятором
			return fragment.Select(s => s.Substring(tabSymbosCount)).ToList();
		}
		
		public override void Parse(IList<string> scriptText)
		{
			for (int line = 0; line < scriptText.Count; line++) {
				string currentLine = scriptText[line];
				if (currentLine.Length <= 0) // пустая строка
					continue;
				if (currentLine[0] == '#') // линейный коментарий от начала строки #
					continue;
				
				int nextCommandLine;
				for (nextCommandLine = line+1;
				     nextCommandLine < scriptText.Count &&
				     scriptText[nextCommandLine].Length > 0 &&
				     (scriptText[nextCommandLine][0] ==	'\t' ||
				      scriptText[nextCommandLine][0] == ' ');
				     nextCommandLine++);//	 Console.WriteLine("for-line: {0}", nextCommandLine);
				int lastCommandLine = nextCommandLine - 1;
				//Console.WriteLine("line = {0}; lastCommandLine = {1}; nextCommandLine = {2}; scriptText.Count = {3}",
				//                  line, lastCommandLine, nextCommandLine, scriptText.Count);
				commands.Add(script.ParseCommand(PrepareFragmentForParse(scriptText.GetFragment(line, lastCommandLine))));
				line = lastCommandLine;
			}
		}
		
		public override string Name {
			get {
				return "Block";
			}
		}
	}
}

